#include "File.h"
#include <windows.h>

std::string File::currentWorkDirectory;

File::File(const FilePath& filepath)
{
	SetPath(filepath);
	SetFileInfo();
}

File::File(const File& rhs): alias(rhs.alias), path(rhs.path), fullpath(rhs.fullpath), attributes(rhs.attributes), date(rhs.date), exists(rhs.exists), size(rhs.size)
{
}

File::~File()
{
}

void File::SetPath(const FilePath& filepath)
{
	if (filepath.IsAbsolute())
		path = filepath;
	else
		path = FilePath(CurrentWorkDirectory()) + filepath;

	path.Resolve();

	fullpath = path.PathString();
	alias = path.FilenameString();
}

const std::string& File::CurrentWorkDirectory()
{
	if (currentWorkDirectory.length() == 0)
	{
		char workPathBuffer[MAX_PATH];

		if (GetCurrentDirectory(sizeof(workPathBuffer), workPathBuffer) == 0)
		{
			throw "File: Could not get current directory";
		}

		currentWorkDirectory.assign(workPathBuffer);
	}

	return currentWorkDirectory;
}

bool File::Delete()
{
	bool result = false;
	
	if (DeleteFile(PathString().c_str()))
		result = true;

	SetFileInfo();

	return result;
}



bool File::MakeDir()
{
	bool result = false;

	if (CreateDirectory(PathString().c_str(), 0))
		result = true;


	SetFileInfo();

	return result;
}

bool File::RemoveDir()
{
	bool result = false;


	if (RemoveDirectory(PathString().c_str()))
		result = true;

	SetFileInfo();

	return result;
}

void File::SetFileInfo()
{
	WIN32_FILE_ATTRIBUTE_DATA fileInfo;

	attributes = NONE;
	size = 0;
	exists = false;

	if (GetFileAttributesEx(PathString().c_str(), GetFileExInfoStandard, &fileInfo))
	{
		SYSTEMTIME stUTC, stLocal;
		DWORD dwAttributes = fileInfo.dwFileAttributes;

		// Extract file attributes
		if (dwAttributes & FILE_ATTRIBUTE_ARCHIVE)
			SetArchiveAttribute();
		if (dwAttributes & FILE_ATTRIBUTE_COMPRESSED)
			SetCompressedAttribute();
		if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
			SetDirectoryAttribute();
		if (dwAttributes & FILE_ATTRIBUTE_HIDDEN)
			SetHiddenAttribute();
		if (dwAttributes & FILE_ATTRIBUTE_READONLY)
			SetReadOnlyAttribute();
		if (dwAttributes & FILE_ATTRIBUTE_SYSTEM)
			SetSystemAttribute();

		// Extract file size
		size = fileInfo.nFileSizeHigh*(1ULL<<32) + fileInfo.nFileSizeLow;


		// Extract file date
		FileTimeToSystemTime(&fileInfo.ftCreationTime, &stUTC);
		SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

		date.SetYear(stLocal.wYear);
		date.SetMonth(stLocal.wMonth);
		date.SetDay(stLocal.wDay);
		date.SetHour(stLocal.wHour);
		date.SetMinute(stLocal.wMinute);
		date.SetSecond(stLocal.wSecond);

		exists = true;
	}
}

void File::SetAttribute(Attributes attr)
{
	attributes = (Attributes)( (unsigned int)attributes | (unsigned int)attr );
}

bool File::GetAttribute(Attributes attr) const
{
	if ( (unsigned int)attributes & (unsigned int)attr )
		return true;
	else
		return false;
}



bool File::operator==(const File& rhs)
{
	return Path() == rhs.Path();
}

bool File::ContainsFile(const File& file)
{
	bool fileFound = false;

	if (IsDirectory() && file.path.HasPrefix( this->path ))
		fileFound = true;

	return fileFound;
}